﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using YesBlog.Domain;
using YesBlog.Infrastructure.Context;
using Z.EntityFramework.Plus;

namespace YesBlog.Repository
{
    /// <summary>
    /// 仓储
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public class EfRepository<TEntity> : IRepository<TEntity> where TEntity : class
    {
        private readonly IDbContext _context;
        private DbSet<TEntity> _entities;

        /// <summary>
        /// 用指定上下文构造新的实例
        /// </summary>
        /// <param name="context"></param>
        public EfRepository(IDbContext context)
        {
            _context = context;
        }

        protected virtual DbSet<TEntity> Entities
        {
            get
            {
                if (_entities == null)
                    _entities = _context.Set<TEntity>();
                return _entities;
            }
        }

        /// <summary>
        /// 实体集合
        /// </summary>
        public virtual IQueryable<TEntity> Table => Entities;


        /// <summary>
        /// 实体集合AsNoTracking
        /// </summary>
        public virtual IQueryable<TEntity> TableNoTracking => Entities.AsNoTracking();

        /// <summary>
        /// 按条件查询实体
        /// </summary>
        /// <param name="where"></param>
        /// <param name="isTracking"></param>
        /// <returns></returns>
        public virtual IQueryable<TEntity> Query(Expression<Func<TEntity, bool>> where, bool isTracking = false)
        {
            return isTracking ? Entities.Where(where) : Entities.AsNoTracking().Where(where);
        }

        /// <summary>
        /// 统计总数
        /// </summary>
        /// <returns></returns>
        public virtual int Count()
        {
            return Entities.Count();
        }

        /// <summary>
        /// 按条件统计
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public virtual int Count(Expression<Func<TEntity, bool>> where)
        {
            return Entities.Count(where);
        }


        /// <summary>
        /// 根据主键得到一个实体
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public virtual TEntity Get(object key)
        {
            return Entities.Find(key);
        }

        /// <summary>
        /// 根据组合主键得到一个实体
        /// 顺序需要根据实体类主键保持一致
        /// Column(Order = 顺序)
        /// </summary>
        /// <param name="keys"></param>
        /// <returns></returns>
        public virtual TEntity Get(params object[] keys)
        {
            return Entities.Find(keys);
        }

        /// <summary>
        /// 按条件查询单个实体
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public virtual TEntity Get(Expression<Func<TEntity, bool>> where)
        {
            return Entities.FirstOrDefault(where);
        }

        /// <summary>
        /// 新增一个实体
        /// </summary>
        /// <param name="entity"></param>
        public virtual void Insert(TEntity entity)
        {
            Entities.Add(entity);
            _context.SaveChanges();

        }

        /// <summary>
        /// 批量新增
        /// </summary>
        /// <param name="entities"></param>
        public virtual void Insert(IEnumerable<TEntity> entities)
        {
            foreach (var entity in entities)
            {
                Entities.Add(entity);
            }
            _context.SaveChanges();
        }


        /// <summary>
        /// 更新实体数据
        /// </summary>
        /// <param name="entity"></param>
        public virtual void Update(TEntity entity)
        {
               var innerContext = (DbContext)_context;
            innerContext.Entry(entity).State = EntityState.Modified;
            _context.SaveChanges();


        }


        /// <summary>
        /// 根据条件批量更新
        /// </summary>
        /// <param name="where"></param>
        /// <param name="func"></param>
        public virtual void Update(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TEntity>> func)
        {
            Entities.Where(where).Update(func);
        }


        /// <summary>
        /// 批量更新
        /// </summary>
        /// <param name="entities"></param>
        public virtual void Update(IEnumerable<TEntity> entities)
        {
            var innerContext = (DbContext)_context;
            foreach (var entity in entities)
            {
                innerContext.Entry(entity).State = EntityState.Modified;
            }
            _context.SaveChanges();
        }

        /// <summary>
        /// 删除实体数据
        /// </summary>
        /// <param name="entity"></param>
        public virtual void Delete(TEntity entity)
        {
            Entities.Remove(entity);
            _context.SaveChanges();
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="where"></param>
        public virtual void Delete(Expression<Func<TEntity, bool>> where)
        {
            IEnumerable<TEntity> entities = Entities.Where(where).AsEnumerable();
            foreach (var entity in entities)
            {
                Entities.Remove(entity);
            }
            _context.SaveChanges();
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="entities"></param>
        public virtual void Delete(IEnumerable<TEntity> entities)
        {
            foreach (var entity in entities)
            {
                Entities.Remove(entity);
            }
            _context.SaveChanges();
        }

    }
}
